﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace Aim2.Screen {
    public class Tiles {
        public bool DoRotation { get; set; }
        const int tileSize = 10;
        public Texture2D TileTexture { get; set; }
        FloatTransition transitionTilesSizeX;
        FloatTransition transitionTilesSizeY;
        FloatTransition transitionTilesSpeed;
        float rotation = 0f;
        const int numberOfTiles = 40;
        const int numberOfTilesLayers = 8;
        float tilesSpeedFactor = 1f;
        float tilesSizeFactorX = 1f;
        float tilesSizeFactorY = 1f;

        private Vector2 lastPosition;
        private Vector2 position;
        private Vector2[] tiles;

        static readonly Color[] tilesColors = new Color[numberOfTilesLayers] { 
            new Color(255, 255, 255, 255), 
            new Color(255, 255, 255, 216), 
            new Color(255, 255, 255, 192), 
            new Color(255, 255, 255, 160), 
            new Color(255, 255, 255, 128), 
            new Color(255, 255, 255, 96), 
            new Color(255, 255, 255, 64), 
            new Color(255, 255, 255, 32) 
        };

        static readonly float[] tilesMovementFactors = new float[numberOfTilesLayers] {
            5.0f, 4.2f, 3.1f, 2.1f, 1.0f, 0.4f, 0.3f, 0.2f
        };

        public Tiles() {
            tiles = new Vector2[numberOfTiles];
        }

        public void LoadContent(GraphicsDevice graphicsDevice, Color secondaryColor) {
            TileTexture = new Texture2D(graphicsDevice, 1, 1, false, SurfaceFormat.Color);
            TileTexture.SetData<Color>(new Color[] { secondaryColor });
        }

        public void UnloadContent() {
            if (TileTexture != null) {
                TileTexture.Dispose();
                TileTexture = null;
            }
        }

        public void Reset(int viewportWidth, int viewportHeight, Vector2 position) {
            for (int i = 0; i < tiles.Length; ++i) {
                tiles[i] = new Vector2(Game.Random.Next(0, viewportWidth),
                    Game.Random.Next(0, viewportHeight));
            }

            this.lastPosition = this.position = position;
        }

        public void Draw(Vector2 position, GraphicsDevice graphicsDevice, SpriteBatch spriteBatch, Color secondaryColor, Rectangle backgroundRectangle) {
            this.lastPosition = this.position;
            this.position = position;

            

            Vector2 movement = (position - lastPosition);

            
            /*if (movement.Length() > maximumMovementPerUpdate) {
                Reset(position);
                return;
            }*/
            spriteBatch.Begin(SpriteSortMode.Deferred, Background.MaxBlend);
            for (int i = 0; i < tiles.Length; i++) {
                int depth = i % tilesMovementFactors.Length;
                tiles[i] += movement * tilesMovementFactors[depth] * tilesSpeedFactor;

                if (tiles[i].X < backgroundRectangle.X) {
                    tiles[i].X = backgroundRectangle.X + backgroundRectangle.Width;
                    tiles[i].Y = backgroundRectangle.Y +
                        Game.Random.Next(backgroundRectangle.Height);
                }
                if (tiles[i].X > (backgroundRectangle.X + backgroundRectangle.Width)) {
                    tiles[i].X = backgroundRectangle.X;
                    tiles[i].Y = backgroundRectangle.Y +
                        Game.Random.Next(backgroundRectangle.Height);
                }
                if (tiles[i].Y < backgroundRectangle.Y) {
                    tiles[i].X = backgroundRectangle.X +
                        Game.Random.Next(backgroundRectangle.Width);
                    tiles[i].Y = backgroundRectangle.Y + backgroundRectangle.Height;
                }
                if (tiles[i].Y >
                    (backgroundRectangle.Y + graphicsDevice.Viewport.Height)) {
                    tiles[i].X = backgroundRectangle.X +
                        Game.Random.Next(backgroundRectangle.Width);
                    tiles[i].Y = backgroundRectangle.Y;
                }

                Rectangle destRect = new Rectangle((int)tiles[i].X, (int)tiles[i].Y, (int)(((tileSize * i / tiles.Length) + 10) * tilesSizeFactorX), (int)(((tileSize * i / tiles.Length + 10) + 1 * tilesSizeFactorY)));
                if (DoRotation) {
                    spriteBatch.Draw(TileTexture,
                        destRect,
                        null,
                        tilesColors[depth],
                        rotation + i, new Vector2(destRect.Width / 2, destRect.Height / 2), SpriteEffects.None, 1.0f
                        );
                }
                else {
                    spriteBatch.Draw(TileTexture,
                       destRect,
                       null,
                       tilesColors[depth]);
                }
            }
            spriteBatch.End();
            if (DoRotation)
                rotation = (rotation + 0.005f) % (MathHelper.Pi * 2);
        }

        public void Update(float elapsed) {
            if (transitionTilesSizeX != null) {
                transitionTilesSizeX.Update(elapsed);
                tilesSizeFactorX = transitionTilesSizeX.CurrentValue;
                if (transitionTilesSizeX.IsOver())
                    transitionTilesSizeX = null;
            }
            if (transitionTilesSizeY != null) {
                transitionTilesSizeY.Update(elapsed);
                tilesSizeFactorY = transitionTilesSizeY.CurrentValue;
                if (transitionTilesSizeY.IsOver())
                    transitionTilesSizeY = null;
            }
            if (transitionTilesSpeed != null) {
                transitionTilesSpeed.Update(elapsed);
                tilesSpeedFactor = transitionTilesSpeed.CurrentValue;
                if (transitionTilesSpeed.IsOver())
                    transitionTilesSpeed = null;
            }
        }

        public void InitTransitionTilesSizeX(float t, float v) {
            transitionTilesSizeX = new FloatTransition(t, v, tilesSizeFactorX);
        }

        public void InitTransitionTilesSizeY(float t, float v) {
            transitionTilesSizeY = new FloatTransition(t, v, tilesSizeFactorY);
        }

        public void InitTransitionTilesSpeed(float t, float v) {
            transitionTilesSpeed = new FloatTransition(t, v, tilesSpeedFactor);
        }

        public void Dispose() {
            if (TileTexture != null) {
                TileTexture.Dispose();
                TileTexture = null;
            }
        }
    }
}
